package com.hopes.bizz.common.core.util;

import cn.hutool.core.collection.CollectionUtil;

import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;


/**  
 * 集合(List,Map,Set)辅助类。  <br>
 * 1.randomOne-从List中随机取出一个元素<br>
 * 2.randomOne-从数组中随机取出一个元素<br>
 * 3.randomNumber-生成一个在最大数和最小数之间的随机数<br>
 * 4.arrayContain-数组中是否存在这个元素<br>
 * 5.addArrayToList-向list中添加数组<br>
 * 6.reverseArray-将数组进行反转，倒置<br>
 * 7.arrayToList-将数组转为list<br>
 * 8.listToArray-将list转为数组<br>
 * 9.concatenateArrays-将一个字符串数组的内容全部添加到另外一个数组中，并返回一个新数组<br>
 * 10.addObjectToArray-将一个object添加到一个数组中，并返回一个新数组<br>
 * 11.isEmpty-集合是否为空(数组，list，map)
 * @author 窦旭彬
 * @date 2015年10月12日  
 */ 

public class CollectionUtils extends CollectionUtil {

	/**
	 * 
	 * 从List中随机取出一个元素 <br>
	 * 从list列表中随机取出list中的某一个元素
	 * @param list 源List
	 * @return T List的一个元素 <br>
	 * eq: list{1,2,3,4} return 2
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> T randomOne(List<T> list){
		if(isEmpty(list)){
			return null;
		}
		return list.get(randomNumber(0, list.size()));
	}
	
	/**
	 * 
	 * 从数组中随机取出一个元素 <br>
	 * 从数组中随机取出一个元素
	 * @param objs 数组
	 * @return T 数组的一个元素<br>
	 * eq：数组T[1,2,3,5] return 5
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> T randomOne(T[] objs){
		if(isEmpty(objs)){
			return null;
		}
		return objs[randomNumber(0, objs.length)];
	}
	
	/**
	 * 
	 * 生成一个在最大数和最小数之间的随机数 <br>
	 * 会出现最小数，但不会出现最大数，如果最大数小于最小数会出现异常
	 * @param minNum 最小数
	 * @param maxNum 最大数
	 * @return 最大数和最小数之间的随机数<br>
	 * eq：minNum：2  maxNum：10 resturn 6
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static int randomNumber(int minNum, int maxNum) {  
		if (maxNum <= minNum) {  
			throw new RuntimeException("maxNum必须大于minNum!");  
		}  
		// 计算出来差值  
		int subtract = maxNum - minNum;  
		Double ranDouble = Math.floor(Math.random() * subtract);  
		return ranDouble.intValue() + minNum;  
	}  
	
	/**
	 * 功能：数组中是否存在这个元素。
	 * @author 窦旭彬
	 * @date 2015年10月12日
	 * @param objArr 数组
	 * @param compare 元素
	 * @return 存在返回true，否则返回false。
	 */
	/**
	 * 
	 * 数组中是否存在这个元素 <br>
	 * 这个元素是否存在数组中，数组T[] 中必须有值，如果空的则返回false
	 * @param objArr 数组
	 * @param compare 元素
	 * @return 存在返回true  不存在返回false<br>
	 * eq：数组[1,2,3,5,6,8] 1.元素 3 return true 2.元素11 return fasle
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> boolean arrayContain(T[] objArr,T compare){
		if(isEmpty(objArr)){
			return false;
		}
		for(T obj : objArr){
			if(obj.equals(compare)){
				return true;
			}
		}
		return false;
	}

	/**
	 * 
	 * 向list中添加数组 <br>
	 * 向list中添加数组,list不能为空
	 * @param list 集合
	 * @param array 数组
	 * eq：list{1,2,3,5} array[7,8,9]   list{1,2,3,5,7,8,9}
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> void addArrayToList(List<T> list, T[] array) {
		if (isEmpty(list)) {
			return;
		}
		for (T t : array) {
			list.add(t);
		}
	}
	
	/**
	 * 功能：将数组进行反转，倒置。
	 * @author 窦旭彬
	 * @date 2015年10月12日
	 * @param objs 源数组
	 * @return T[] 反转后的数组
	 */
	/**
	 * 
	 * 将数组进行反转，倒置 <br>
	 * 将数组进行反转，倒置,数组不为空，如果为空则返回null
	 * @param objs 源数组
	 * @return T[] 反转后的数组<br>
	 * eq:[1,2,3,4,5] return [5,4,3,2,1]
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] reverseArray(T[] objs){
		if(isEmpty(objs)){
			return null;
		}
		T[] res=(T[])java.lang.reflect.Array.newInstance(objs[0].getClass(), objs.length);
		//新序号
		int k=0;
		for(int i=objs.length-1 ; i>=0 ; i--){
			res[k++]=objs[i];
		}
		return res;
	}
	
	/**
	 * 
	 * 将数组转为list <br>
	 * 将数组转为list，如果数组是空的返回null
	 * @param objs 数组
	 * @return list集合<br>
	 * eq:[1,2,3] return {1,2,3}
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> List<T> arrayToList(T[] objs){
		if(isEmpty(objs)){
			return null;
		}
		List<T> list=new LinkedList<T>();
		for(T obj : objs){
			list.add(obj);
		}
		return list;
	}
	
	/**
	 * 
	 * 将list转为数组 <br>
	 * 将list转为数组,如果list集合为空则返回null 
	 * @param list
	 * @return T[] 数组<br>
	 * eq:{1,2,3,5} return [1,2,3,5]
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] listToArray(List<T> list){
		if(isEmpty(list)){
			return null;
		}
		T[] objs=(T[])java.lang.reflect.Array.newInstance(list.get(0).getClass(), list.size());
		int i=0; //数组下标。
		for(T obj : list){
			objs[i++]=obj;
		}
		return objs;
	}
	
	/**
	 * 
	 * 将一个字符串数组的内容全部添加到另外一个数组中，并返回一个新数组 <br>
	 * 将一个数组的内容全部添加到另外一个数组中，并返回一个新数组,如果数组1为空则返回数组2，如果数组2为空则返回数组1
	 * @param array1 第一个数组
	 * @param array2 第二个数组
	 * @return T[] 拼接后的新数组<br>
	 * eq:[1,2,4] , [7,8,9] return [1,2,4,7,8,9]
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] concatenateArrays(T[] array1, T[] array2) {
		if (isEmpty(array1)) {
			return array2;
		}
		if (isEmpty(array2)) {
			return array1;
		}
		T[] resArray=(T[])java.lang.reflect.Array.newInstance(array1[0].getClass(), array1.length+array2.length);
		System.arraycopy(array1, 0, resArray, 0, array1.length);
		System.arraycopy(array2, 0, resArray, array1.length, array2.length);
		return resArray;
	}
	
	/**
	 * 将一个object添加到一个数组中，并返回一个新数组。
	 * @param array被添加到的数组
	 * @param object 被添加的object
	 * @return T[] 返回的新数组
	 */
	/**
	 * 
	 * 将一个object添加到一个数组中，并返回一个新数组 <br>
	 * 将一个object添加到一个数组中,如果数组为空，返回obj的数组
	 * @param array 被添加到的数组
	 * @param obj 被添加的object
	 * @return T[] 返回的心数组<br>
	 * eq:[1,2,4] 6 return [1,2,4,6]
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("unchecked")
	public static <T> T[] addObjectToArray(T[] array, T obj) {
		//结果数组
		T[] resArray=null;
		if (isEmpty(array)) {
			resArray=(T[])java.lang.reflect.Array.newInstance(obj.getClass(), 1);
			resArray[0]=obj;
			return resArray;
		}
		//原数组不为空时。
		resArray=(T[])java.lang.reflect.Array.newInstance(array[0].getClass(), array.length+1);
		System.arraycopy(array, 0, resArray, 0, array.length);
		resArray[array.length] = obj;
		return resArray;
	}
	
	/**
	 * 
	 * 判断数组是不是空。 <br>
	 * 判断数组是不是空。（null或者length==0）
	 * @param array 数组
	 * @return boolean 空返回true，否则返回false<br>
	 * eq:[] return ture , [1,2] return false
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	public static <T> boolean isEmpty(T[] array) {
		return (array == null || array.length==0);
	}
	
	/**
	 * 
	 * 集合是否为空 <br>
	 * 集合是否为空。如果传入的值为null或者集合不包含元素都认为为空。
	 * @param collection 集合
	 * @return boolean 为空返回true，否则返回false。<br>
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("rawtypes")
	public static boolean isEmpty(Collection collection) {
		return (collection == null || collection.isEmpty());
	}

    /**
     * 集合非null并且size大于0
     * @param collection
     * @return
     */
	public static boolean isNotEmpty(Collection collection){
        return (collection != null && !collection.isEmpty());
    }

	/**
	 * 
	 * Map是否为空 <br>
	 * Map是否为空。如果传入的值为null或者集合不包含元素都认为为空。
	 * @param map 集合
	 * @return boolean 为空返回true，否则返回false。
	 * @author douxubin@nfky.com
	 * @since [1.0.0]
	 * @version [1.0.0,2015年10月22日]
	 */
	@SuppressWarnings("rawtypes")
	public static boolean isEmpty(Map map) {
		return (map == null || map.isEmpty());
	}

    /**
     * Map非null并且size大于0
     * @param map
     * @return
     */
    public static boolean isNotEmpty(Map map) {
        return (map != null && !map.isEmpty());
    }
}


